package gui;

import iface.ChartInfo;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;

import javax.swing.JPanel;

/**
 * Simple bar chart panel which is only a slight modification of the tutorial
 * code from
 * http://www.roseindia.net/java/example/java/swing/draw-simple-bar-chart.shtml.
 */
public class SimpleBarChart extends JPanel {
    /** Generated UID */
    private static final long serialVersionUID = 5492312560235092275L;
    private double[] value;
    private String[] labels;
    private String title;
    
    /**Defines the distance in pixel for the label to the upper edge of the chart piece.*/
    private static final int DISTANCE_FROM_UPPER_EDGE = -5;

    /**
     * Constructor of this class.
     * 
     * @param info information which is used to build the chart.
     * @param t the title of the chart.
     */
    public SimpleBarChart(ChartInfo info, String t) {
	this.labels = info.getNames();
	this.value = info.getValues();
	this.title = t;
	repaint();
    }

    /**
     * Updates the chart with the given values.
     * 
     * @param info values for the chart
     * @param t title of the chart
     */
    public void updateValues(ChartInfo info, String t) {
	this.labels = info.getNames();
	this.value = info.getValues();
	this.title = t;
	repaint();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void paintComponent(Graphics graphics) {
	super.paintComponent(graphics);
	if (this.value == null || this.value.length == 0)
	    return;
	double minValue = Double.POSITIVE_INFINITY;
	double maxValue = Double.NEGATIVE_INFINITY;

	for (int i = 0; i < this.value.length; i++) {
	    if (minValue > this.value[i])
		minValue = this.value[i];
	    if (maxValue < this.value[i])
		maxValue = this.value[i];
	}

	Dimension dim = getSize();
	int clientWidth = dim.width;
	int clientHeight = dim.height;
	int barWidth = clientWidth / this.value.length;

	Font titleFont = new Font("Book Antiqua", Font.BOLD, 15);
	FontMetrics titleFontMetrics = graphics.getFontMetrics(titleFont);
	Font labelFont = new Font("Book Antiqua", Font.BOLD, 12);
	FontMetrics labelFontMetrics = graphics.getFontMetrics(labelFont);

	int titleWidth = titleFontMetrics.stringWidth(this.title);
	int q = titleFontMetrics.getAscent();
	int p = (clientWidth - titleWidth) / 2;
	graphics.setFont(titleFont);
	graphics.drawString(this.title, p, q);
	int top = titleFontMetrics.getHeight();
	int bottom = labelFontMetrics.getHeight();

	if (maxValue == minValue) {
	    return;
	}

	double scale = (clientHeight - top - bottom) / (maxValue - minValue);
	q = clientHeight - labelFontMetrics.getDescent();

	graphics.setFont(labelFont);

	for (int j = 0; j < this.value.length; j++) {
	    double actualValue = this.value[j];

	    int valueP = j * barWidth + 1;
	    int valueQ = top;
	    int height = (int) (actualValue * scale);
	    
	    if (this.value[j] >= 0)
		valueQ += (int) ((maxValue - actualValue) * scale);
	    else {
		valueQ += (int) (maxValue * scale);
		height = -height;
	    }

	    if (actualValue == maxValue) {
		graphics.setColor(Color.green);
	    } else if (actualValue == minValue) {
		graphics.setColor(Color.red);
	    } else {
		graphics.setColor(Color.blue);
	    }

	    graphics.fillRect(valueP, valueQ, barWidth - 2, height);
	    graphics.setColor(Color.black);
	    graphics.drawRect(valueP, valueQ, barWidth - 2, height);

	    int labelWidth = labelFontMetrics.stringWidth(this.labels[j]);
	    p = j * barWidth + (barWidth - labelWidth) / 2;
	    
	    graphics.drawString(this.labels[j], p, (valueQ + DISTANCE_FROM_UPPER_EDGE));
	}
    }
}
